package com.clx.channelHandler.hander;

import com.clx.CrpcBootstrap;
import com.clx.ServiceConfig;
import com.clx.enumeration.RequestType;
import com.clx.enumeration.RespCode;
import com.clx.transport.message.CrpcRequest;
import com.clx.transport.message.CrpcResponse;
import com.clx.transport.message.RequestPayload;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Slf4j
public class MethodCallHander extends SimpleChannelInboundHandler<CrpcRequest> {
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, CrpcRequest crpcRequest) throws Exception {
        // 1.获取负载内容
        RequestPayload requestPayload = crpcRequest.getRequestPayload();

        // 2.根据负载内容进行方法调用
        Object result = null;
        if (!(crpcRequest.getRequestType() == RequestType.HEART_BEAT.getId())){
               result = callTargetMethod(requestPayload);
            if (log.isDebugEnabled()){
                log.debug("请求【{}】已经在服务端完成方法调用。",crpcRequest.getRequestId());
            }
        }
        //  封装响应
        CrpcResponse crpcResponse = new CrpcResponse();
        crpcResponse.setCode(RespCode.SUCCESS.getCode());
        crpcResponse.setRequestId(crpcRequest.getRequestId());
        crpcResponse.setCompressType(crpcRequest.getCompressType());
        crpcResponse.setSerializeType(crpcRequest.getSerializeType());
        crpcResponse.setBody(result);

        // 4.写出响应
        channelHandlerContext.channel().writeAndFlush(crpcResponse);
    }

    private Object callTargetMethod(RequestPayload requestPayload) {
        String interfaceName = requestPayload.getInterfaceName();
        String methodName = requestPayload.getMethodName();
        Class<?>[] parametersType = requestPayload.getParametersType();
        Object[] parametersValue = requestPayload.getParametersValue();

        // 寻找到匹配的暴露出去的具体的实现
        ServiceConfig<?> serviceConfig = CrpcBootstrap.SERVERS_LIST.get(interfaceName);
        Object refImpl = serviceConfig.getRef();

        // 通过反射调用 1,获取方法对象 2，执行invoke方法
        Object returnValue;
        try{
            Class<?> aClass = refImpl.getClass();
            Method method = aClass.getMethod(methodName, parametersType);
            // 修复：将 parametersType 改为 parametersValue（传递“参数值”而非“参数类型”）
            returnValue = method.invoke(refImpl, parametersValue);
        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
            log.error("调用服务【{}】的方法【{}】时发生了异常",interfaceName,methodName,e);
            throw  new RuntimeException(e);
        }
        return returnValue;
    }
}
